package com.qzsoft.zhjd.monitoring.modules.zlm.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qzsoft.zhjd.monitoring.config.ZLMServerConfig;
import com.qzsoft.zhjd.monitoring.modules.zlm.manager.ZLMServerManager;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName ZlmHttpHookController
 * @Description ZLM 服务 hook api
 * @author linhuawei
 * @since 2022-03-22
 */
@Slf4j
@RestController
@RequestMapping("/index/hook")
public class ZlmHttpHookController {
    
    @Autowired
    private ZLMServerManager zlmServerManager;

    /**
     * @Title onFlowReport
     * @Description 流量统计事件，播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件，阈值通过配置文件general.flowThreshold配置；此事件对回复不敏感。
     * @param json
     * @return
     */
    @PostMapping("/on_flow_report")
    public ResponseEntity<String> onFlowReport(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_flow_report API调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onHttpAccess
     * @Description 访问http文件服务器上hls之外的文件时触发。
     * @param json
     * @return
     */
    @PostMapping("/on_http_access")
    public ResponseEntity<String> onHttpAccess(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_http_access API 调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("err", "");
        ret.put("path", "");
        ret.put("second", 600);
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onPlay
     * @Description 播放器鉴权事件，rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。
     * @param json
     * @return
     */
    @PostMapping("/on_play")
    public ResponseEntity<String> onPlay(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_play API调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * 
     *
     */
    /**
     * @Title onPublish
     * @Description rtsp/rtmp/rtp推流鉴权事件。
     * @param json
     * @return
     */
    @PostMapping("/on_publish")
    public ResponseEntity<String> onPublish(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_publish API调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        ret.put("enableHls", true);
        ret.put("enableMP4", false);
        ret.put("enableRtxp", true);
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onRecordMp4
     * @Description 录制mp4完成后通知事件；此事件对回复不敏感。
     * @param json
     * @return
     */
    @PostMapping("/on_record_mp4")
    public ResponseEntity<String> onRecordMp4(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_record_mp4 API调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onRtspRealm
     * @Description rtsp专用的鉴权事件，先触发on_rtsp_realm事件然后才会触发on_rtsp_auth事件。
     * @param json
     * @return
     */
    @PostMapping("/on_rtsp_realm")
    public ResponseEntity<String> onRtspRealm(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_rtsp_realm API调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("realm", "");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onRtspAuth
     * @Description 该rtsp流是否开启rtsp专用方式的鉴权事件，开启后才会触发on_rtsp_auth事件。需要指出的是rtsp也支持url参数鉴权，它支持两种方式鉴权。
     * @param json
     * @return
     */
    @PostMapping("/on_rtsp_auth")
    public ResponseEntity<String> onRtspAuth(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_rtsp_auth API调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("encrypted", false);
        ret.put("passwd", "test");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onShellLogin
     * @Description shell登录鉴权，ZLMediaKit提供简单的telnet调试方式，使用telnet
     *              127.0.0.1:9000能进入MediaServer进程的shell界面。
     * @param json
     * @return
     */
    @PostMapping("/on_shell_login")
    public ResponseEntity<String> onShellLogin(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_shell_login API调用，参数：" + json.toString());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * rtsp/rtmp流注册或注销时触发此事件；此事件对回复不敏感。
     *
     */
    @PostMapping("/on_stream_changed")
    public ResponseEntity<String> onStreamChanged(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_stream_changed API调用，参数：" + json.toString());

        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onStreamNoneReader
     * @Description 流无人观看时事件，用户可以通过此事件选择是否关闭无人看的流。
     * @param json
     * @return
     */
    @PostMapping("/on_stream_none_reader")
    public ResponseEntity<String> onStreamNoneReader(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_stream_none_reader API调用，参数：" + json.toString());
        
//        // 关闭推流数据
//        String app = json.getString("app");
//        String stream = json.getString("stream");
//        zlmServerManager.closeStreamProxy(app, stream);
        
        // TODO 判断是否在录制，如果录制不可关闭

        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("close", true);// 关闭推流代理
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onStreamNotFound
     * @Description 流未找到事件，用户可以在此事件触发时，立即去拉流，这样可以实现按需拉流；此事件对回复不敏感。
     * @param json
     * @return
     */
    @PostMapping("/on_stream_not_found")
    public ResponseEntity<String> onStreamNotFound(@RequestBody JSONObject json) {
        log.info("ZLM HOOK on_stream_not_found API调用，参数：" + json.toString());
        
        // 视频流不存在时，添加推流代理
        String app = json.getString("app");
        String stream = json.getString("stream");
        zlmServerManager.onStreamNotFound(app, stream);

        // 返回结果
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }

    /**
     * @Title onServerStarted
     * @Description 服务器启动事件，可以用于监听服务器崩溃重启；此事件对回复不敏感。
     * @param request
     * @param data
     * @return
     */
    @PostMapping("/on_server_started")
    public ResponseEntity<String> onServerStarted(HttpServletRequest request, @RequestBody String data) {
        JSONObject json = JSONObject.parseObject(data);
        log.info("ZLM HOOK on_server_started API调用，参数：" + json.toString());
        
        // 更新服务器配置
        ZLMServerConfig zlmServerConfig = JSON.toJavaObject(json, ZLMServerConfig.class);
        zlmServerManager.updateCacheServerConfig(zlmServerConfig);
        
        // 返回结果
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        ret.put("msg", "success");
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }
}
